package com.local.mychess;
import android.os.Build;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;

public class DeviceInfor {
    private static final boolean IS_PAPER_PAD_MODE = false;
    private static String serverIp = "8.155.36.201";
    private static String volume = "1";
    private static String check = "true";
    private static final String APP_NAME = "路边象棋";
    private static final String TAG = "DeviceInfor";
    private static final String ID_FILE_NAME = ".device_id.properties";
    private static final String KEY_LOCAL_ID = "local_device_id";
    private static final String CONFIG_FILE_NAME = ".config.properties";
    private static final String CONFIG_IP = "server_ip";
    private static final String CONFIG_VOLUME = "volume";
    private static final String CONFIG_CHECK = "check";

    private static final int ID_LENGTH = 8;
    private static String sCachedId; // 内存缓存，避免重复读取文件

    public static void saveConfig(String serverIp, String volume, String check) {
        File dir = getStoragePath();
        if (!dir.exists() && !dir.mkdirs()) {
            Log.e(TAG, "无法创建存储目录");
            return;
        }

        File file = new File(dir, CONFIG_FILE_NAME);
        Properties props = new Properties();
        props.setProperty(CONFIG_IP, serverIp);
        props.setProperty(CONFIG_VOLUME, volume);
        props.setProperty(CONFIG_CHECK, check);

        try (FileOutputStream fos = new FileOutputStream(file)) {
            props.store(fos, "Config storage");
            DeviceInfor.serverIp = serverIp;
            DeviceInfor.volume = volume;
            DeviceInfor.check = check;
        } catch (IOException e) {
            Log.w(TAG, "保存配置失败", e);
        }
    }

    public static void loadConfig() {
        File file = new File(getStoragePath(), CONFIG_FILE_NAME);
        if (!file.exists()) {
            return;
        }

        Properties props = new Properties();
        try (FileInputStream fis = new FileInputStream(file)) {
            props.load(fis);
            DeviceInfor.serverIp = props.getProperty(CONFIG_IP);
            DeviceInfor.volume = props.getProperty(CONFIG_VOLUME);
            DeviceInfor.check = props.getProperty(CONFIG_CHECK);
        } catch (IOException e) {
            Log.w(TAG, "加载设备属性失败", e);
        }
    }

    public static String getServerIp() {
        return serverIp;
    }
    public static String getVolume() {
        return volume;
    }
    public static String getCheck() {
        return check;
    }

    public static String getAppName() {
        return APP_NAME;
    }

    public static boolean getIsPadMode() {
        return IS_PAPER_PAD_MODE;
    }

    public static String getLocalID() {
        // 1. 先检查内存缓存
        if (sCachedId != null && sCachedId.length() == ID_LENGTH) {
            return sCachedId;
        }

        // 2. 从文件存储中获取
        Properties storedProps = loadPropertiesFromFile();
        String storedId = storedProps.getProperty(KEY_LOCAL_ID);

        if (storedId != null && storedId.length() == ID_LENGTH) {
            sCachedId = storedId;
            return storedId;
        }

        // 3. 存储中没有则生成新ID
        String newId = generateNewLocalID();

        // 4. 持久化存储，确保后续调用结果一致
        saveToFile(newId);
        sCachedId = newId;

        return newId;
    }

    /**
     * 基于设备硬件信息和首次生成时间生成新的16位标识符
     */
    private static String generateNewLocalID() {
        // 收集无需Context和权限的设备信息
        StringBuilder deviceInfo = new StringBuilder();

        // 设备制造商（稳定）
        deviceInfo.append(Build.MANUFACTURER.trim().toLowerCase(Locale.ROOT));
        // 设备型号（稳定）
        deviceInfo.append(Build.MODEL.trim().toLowerCase(Locale.ROOT));
        // 硬件名称（稳定）
        deviceInfo.append(Build.HARDWARE.trim().toLowerCase(Locale.ROOT));
        // 主板信息（稳定）
        deviceInfo.append(Build.BOARD.trim().toLowerCase(Locale.ROOT));
        // 设备品牌（稳定）
        deviceInfo.append(Build.BRAND.trim().toLowerCase(Locale.ROOT));
        // 产品名称（稳定）
        deviceInfo.append(Build.PRODUCT.trim().toLowerCase(Locale.ROOT));
        // 系统版本号（稳定）
        deviceInfo.append(Build.VERSION.SDK_INT);
        // 加入首次生成时间作为参数
        deviceInfo.append(new Date().getTime());

        // 生成SHA-256哈希值
        String hash = generateHash(deviceInfo.toString());

        // 处理为16位字符串
        return processHashTo16Chars(hash);
    }



    /**
     * 哈希算法不可用时的备选方案
     */
    private static String generateHash(String input) {
        int hash = 0;
        for (char c : input.toCharArray()) {
            hash = 31 * hash + c;
        }
        // 扩展哈希长度以确保有足够字符生成16位ID
        String baseHash = Integer.toHexString(Math.abs(hash));
        StringBuilder extendedHash = new StringBuilder(baseHash);
        while (extendedHash.length() < 32) {
            extendedHash.append(Integer.toHexString(Math.abs(31 * extendedHash.toString().hashCode() + 7)));
        }
        return extendedHash.toString();
    }

    /**
     * 将哈希值处理为16位字符串
     */
    private static String processHashTo16Chars(String hash) {
        // 确保哈希有足够长度
        if (hash == null || hash.length() < ID_LENGTH) {
            StringBuilder supplement = new StringBuilder(hash != null ? hash : "");
            while (supplement.length() < ID_LENGTH) {
                supplement.append(generateHash(supplement.toString()));
            }
            hash = supplement.toString();
        }

        // 截取前16位并转为大写
        String result = hash.substring(0, ID_LENGTH).toUpperCase(Locale.ROOT);

        // 确保结果包含数字和字母的混合
        if (result.matches("[0-9]+")) {
            // 全数字时替换部分字符为字母
            char[] chars = result.toCharArray();
            chars[1] = (char) ('A' + (chars[1] % 26));
            chars[4] = (char) ('B' + (chars[4] % 25));
            chars[7] = (char) ('C' + (chars[7] % 24));
            chars[10] = (char) ('D' + (chars[10] % 23));
            chars[13] = (char) ('E' + (chars[13] % 22));
            return new String(chars);
        } else if (result.matches("[A-F]+")) {
            // 全字母时替换部分字符为数字
            char[] chars = result.toCharArray();
            chars[2] = (char) ('0' + (chars[2] % 10));
            chars[5] = (char) ('1' + (chars[5] % 9));
            chars[8] = (char) ('2' + (chars[8] % 8));
            chars[11] = (char) ('3' + (chars[11] % 7));
            chars[14] = (char) ('4' + (chars[14] % 6));
            return new String(chars);
        }

        return result;
    }

    /**
     * 从文件加载属性（包括ID和时间戳）
     */
    private static Properties loadPropertiesFromFile() {
        File file = new File(getStoragePath(), ID_FILE_NAME);
        if (!file.exists()) {
            return new Properties();
        }

        Properties props = new Properties();
        try (FileInputStream fis = new FileInputStream(file)) {
            props.load(fis);
        } catch (IOException e) {
            Log.w(TAG, "加载设备属性失败", e);
        }
        return props;
    }

    /**
     * 从文件加载已保存的ID
     */
    private static String loadFromFile() {
        return loadPropertiesFromFile().getProperty(KEY_LOCAL_ID);
    }

    /**
     * 将生成的ID和首次生成时间保存到文件
     */
    private static void saveToFile(String id) {
        File dir = getStoragePath();
        if (!dir.exists() && !dir.mkdirs()) {
            Log.e(TAG, "无法创建存储目录");
            return;
        }

        File file = new File(dir, ID_FILE_NAME);
        Properties props = new Properties();
        props.setProperty(KEY_LOCAL_ID, id);

        try (FileOutputStream fos = new FileOutputStream(file)) {
            props.store(fos, "Device ID storage");
        } catch (IOException e) {
            Log.w(TAG, "保存设备ID失败", e);
        }
    }

    /**
     * 获取存储路径，优先使用应用数据目录
     */
    private static File getStoragePath() {
        // 尝试获取应用数据目录
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            try {
                Class<?> contextClass = Class.forName("android.content.Context");
                Object applicationContext = contextClass.getMethod("getApplicationContext").invoke(null);
                File dataDir = (File) applicationContext.getClass().getMethod("getDataDir").invoke(applicationContext);
                return new File(dataDir, "device_id");
            } catch (Exception e) {
                // 反射失败时使用备用路径
                Log.w(TAG, "无法获取应用数据目录，使用备用路径", e);
            }
        }

        // 备用路径：系统临时目录
        return new File(System.getProperty("java.io.tmpdir"), "device_id");
    }
}
